# NOTE: only tested in GNU/Linux.

## Binary dependencies.

CC = gcc
AR = ar


## Paths.

PREFIX ?= /usr/local
bindir = $(PREFIX)/bin
libdir = $(PREFIX)/lib
includedir = $(PREFIX)/include/lsup

INCLUDE = -I. -Iinclude -I$(includedir)
# Link all ext libraries statically.
CFLAGS += -Wall -fPIC -MMD $(INCLUDE)
DBG_CFLAGS = -Itest -O0 -g3 -DDEBUG
LDFLAGS = -L. -L$(libdir) -llsuprdf -luuid
DBG_LDFLAGS = -L. -L$(libdir) -llsuprdf_dbg -luuid

SRC = $(wildcard src/*.c)
OBJ = $(SRC:.c=.o)
DBG_OBJ = $(SRC:.c=_dbg.o)

TEST_SRC = $(wildcard test/*.c) test.c

LIBS = liblsuprepo.a liblsuprepo.so
DBG_LIBS = liblsuprepo_dbg.a liblsuprepo_dbg.so


## Environment.

export LD_LIBRARY_PATH = $(libdir):.


## Rules.

.DEFAULT_GOAL := lib


# Extract all rule comment into a help message.
.PHONY: help
help:
	@echo "Command overview:"; echo; \
		grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
		| sed -n 's/^\(.*\): \(.*\)##\(.*\)/\1::\3/p' \
		| column -t  -s '::'


lib: $(LIBS)


debug: $(DBG_LIBS)


liblsuprepo.a: $(OBJ)
	$(AR) rs $@ $^


liblsuprepo.so: $(OBJ)
	$(CC) -shared $(LDFLAGS) -o $@ $^


liblsuprepo_dbg.a: $(DBG_OBJ)
	$(AR) rs $@ $^


liblsuprepo_dbg.so: $(DBG_OBJ)
	$(CC) -shared $(LDFLAGS) -o $@ $^


# Debug objects.
%_dbg.o: %.c
	$(CC) $(CFLAGS) $(DBG_CFLAGS) $(LDFLAGS) -c $^ -o $@


install: lib ## Install default libraries to $PREFIX. May require sudo.
	mkdir -p $(DESTDIR)$(libdir)
	mkdir -p $(DESTDIR)$(includedir)
	cp liblsuprepo.* $(DESTDIR)$(libdir) && \
		cp include/*.h $(EXT_H) $(DESTDIR)$(includedir)


debug_install: install debug ## Install default and debug libraries.
	cp liblsuprdf_dbg.{a,so} $(DESTDIR)$(libdir)
	

.PHONY: clean
clean:
	rm -rf src/*.[aod] ./*[aod]
	rm -f bin/test*


.PHONY: uninstall
uninstall:
	rm -f $(DESTDIR)$(libdir)/liblsuprepo.*
	rm -rf $(DESTDIR)$(includedir)


# For testing, use debug symbols.
bin/test: debug $(TEST_SRC)
	$(CC) $(CFLAGS) $(DBG_CFLAGS) -Itest $(DBG_LDFLAGS) -llsuprepo_dbg \
		test.c -o bin/test


.PHONY: test
test: bin/test ## Run a test suite.
	exec bin/test


.PHONY: gdb_test
gdb_test: bin/test ## Run a test suite within gdb.
	exec gdb bin/test


.PHONY: memcheck
memcheck:
	valgrind \
		--leak-check=full --show-leak-kinds=all --track-origins=yes \
		--log-file=/tmp/lsup_valgrind.log \
		./bin/test
	@echo "Memcheck complete. Valgrind log is at /tmp/lsup_valgrind.log"


memtest: bin/test memcheck ## Run a test suite using Valgrind. Output to separate file.


bin/profile: debug profile.c
	$(CC) $(CFLAGS) -g -DTESTING profile.c $(DBG_LDFLAGS) \
		-llsuprepo_dbg -o bin/profile


.PHONY: profile
profile: bin/profile
	exec valgrind --tool=callgrind --callgrind-out-file="$(CALLGRIND_DUMP)" \
		bin/profile 10000
	@echo "Profile dump written at $(CALLGRIND_DUMP)"


.PHONY: pytest
py_test:
	pip3 install --user .
	python3 test/cpython_test.py
